package com.shensi.adminCollect.controller.station;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.shensi.common.core.domain.AjaxResult;
import com.shensi.adminCollect.common.exception.BaseException;
import com.shensi.adminCollect.common.utils.RSAUtils;
import com.shensi.adminCollect.common.utils.StringUtils;
import com.shensi.adminCollect.domain.customer.ReductionActivityBalanceRecord;
import com.shensi.adminCollect.domain.station.PayOrder;
import com.shensi.adminCollect.domain.station.PhysicalCard;
import com.shensi.adminCollect.domain.station.PhysicalCardBalance;
import com.shensi.adminCollect.domain.station.dto.PhysicalCardBalanceDto;
import com.shensi.adminCollect.domain.station.dto.PhysicalCardOrderDto;
import com.shensi.adminCollect.domain.station.dto.PhysicalCardSecretKeyDto;
import com.shensi.adminCollect.domain.station.vo.PhysicalCardPosVo;
import com.shensi.adminCollect.enums.station.BalanceTypeEnum;
import com.shensi.adminCollect.enums.station.PhysicalCardPaymentEnum;
import com.shensi.adminCollect.service.station.IPhysicalCardBalanceService;
import com.shensi.adminCollect.service.station.IPhysicalCardOrderService;
import com.shensi.adminCollect.service.station.IPhysicalCardService;
import com.shensi.adminCollect.utils.station.RegexUtils;
import com.shensi.adminCollect.domain.system.HttpUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * admin 提供给pos机使用的接口
 * */
@RestController
@RequestMapping("/external")
@Slf4j
public class PhysicalCardExternalController {

    @Value("${physicalCard.secretKeyA}")
    private String SECRET_KEY_A;

    @Value("${physicalCard.secretKeyB}")
    private String SECRET_KEY_B;

    @Value("${physicalCard.external.publicKey}")
    private String publicKey;

    @Value("${physicalCard.external.privateKey}")
    private String privateKey;

    @Value("${physicalCard.external.message}")
    private String messageKey;
    @Value("${qujia.payBaseUrl}")
    private String payBaseUrl;
    @Autowired
    private IPhysicalCardBalanceService physicalCardBalanceService;

    @Autowired
    private IPhysicalCardService physicalCardService;

    @Autowired
    private IPhysicalCardOrderService physicalCardOrderService;


    /**实体卡充值*/
    @PostMapping("/recharge")
    @ApiOperation(value = "实体卡充值",response = PhysicalCardSecretKeyDto.class)
    @Transactional
    public AjaxResult recharge(@RequestBody PhysicalCardBalanceDto physicalCardBalanceDto){
        if(Objects.isNull(physicalCardBalanceDto) || StringUtils.isEmpty(physicalCardBalanceDto.getPhysicalCardNo())
                || StringUtils.isEmpty(physicalCardBalanceDto.getMessage())){
            return AjaxResult.error("请求参数异常");
        }
        physicalCardBalanceDto.setPhysicalCardNo(StringUtils.trim(physicalCardBalanceDto.getPhysicalCardNo()));
        // 密文校验
        if(!checkMessage(physicalCardBalanceDto.getMessage())){
            return AjaxResult.error("密文校验失败");
        }

        PhysicalCardBalance physicalCardBalance = new PhysicalCardBalance();
        BeanUtils.copyProperties(physicalCardBalanceDto,physicalCardBalance);
        log.info("PhysicalCardBalanceController.recharge请求参数：[{}]", JSONObject.toJSONString(physicalCardBalance));
        if(Objects.isNull(physicalCardBalance.getAmount())){
            return AjaxResult.error("请输入充值金额");
        }
        PhysicalCard physicalCard = physicalCardService.selectPhysicalCard(physicalCardBalance.getPhysicalCardNo());
        if(Objects.isNull(physicalCard)){
            return AjaxResult.error("实体卡不存在");
        }
        if(StringUtils.isEmpty(physicalCard.getStationId()) || StringUtils.isEmpty(physicalCardBalanceDto.getCurrStationId())){
            return AjaxResult.error("油站不存在");
        }
        checkStationId(physicalCard.getStationId(),physicalCardBalanceDto.getCurrStationId());
        if(physicalCardService.physicalCardType(physicalCard)){
            return AjaxResult.error("定额卡不允许充值");
        }
        // 修改实体卡面额
        BigDecimal amount = BigDecimal.ZERO;
        if(Objects.isNull(physicalCard.getPhysicalCardAmount())
                || (physicalCard.getPhysicalCardAmount().signum() == 0)){
            physicalCard.setPhysicalCardAmount(physicalCardBalance.getAmount());
            physicalCardService.updatePhysicalCard(physicalCard);
            physicalCardBalance.setBalanceAmount(physicalCardBalance.getAmount());
        } else {
            amount = physicalCard.getPhysicalCardAmount().add(physicalCardBalance.getAmount());
            physicalCard.setPhysicalCardAmount(amount);
            physicalCardService.updatePhysicalCard(physicalCard);
            physicalCardBalance.setBalanceAmount(amount);
        }

        //增加充值记录
        physicalCardBalance.setBalanceType(BalanceTypeEnum.RECHARGE.getValue());
        physicalCardBalance.setEnterpriseId(physicalCard.getEnterpriseId());
        physicalCardBalance.setEnterpriseName(physicalCard.getEnterpriseName());
        physicalCardBalance.setStationId(physicalCardBalanceDto.getCurrStationId());
        physicalCardBalance.setPayment(PhysicalCardPaymentEnum.XJ.getValue());
        PhysicalCardSecretKeyDto physicalCardSecretKeyDto = physicalCardBalanceService.addPhysicalCardBalance(physicalCardBalance);

        String url = payBaseUrl+"/reductionActivity/createActivityBalanceRecord";
        ReductionActivityBalanceRecord record=new ReductionActivityBalanceRecord();
        record.setRechargeAmt(physicalCardBalance.getAmount());
        record.setPhysicalCardNo(physicalCardBalance.getPhysicalCardNo());
        record.setPaymentMethod("xj");
        record.setEnterpriseId(physicalCard.getEnterpriseId());
        String resultJson = "";
        try {
            resultJson = HttpUtils.connectPostUrl(url, JSON.toJSONString(record));
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("立减活动返回信息：" + resultJson);

        if(Objects.isNull(physicalCardSecretKeyDto) || StringUtils.isEmpty(physicalCardSecretKeyDto.getOrderNo())){
            return AjaxResult.error("充值失败");
        }

        PhysicalCardPosVo physicalCardPosVo = new PhysicalCardPosVo();
        physicalCardPosVo.setPhysicalCardNo(physicalCardBalance.getPhysicalCardNo());
        physicalCardPosVo.setOrderNo(physicalCardSecretKeyDto.getOrderNo());
        physicalCardPosVo.setAmt(physicalCardBalanceDto.getAmount());
        physicalCardPosVo.setCreateTime(new Date());
        physicalCardPosVo.setBalance(amount);
        physicalCardPosVo.setCustomerName(physicalCard.getUserName());
        physicalCardPosVo.setMobilePhone(physicalCard.getUserPhone());

        return AjaxResult.success(physicalCardPosVo);
    }

    private void checkStationId(String stationIds, String currStationId){
        if(StringUtils.isEmpty(stationIds) || StringUtils.isEmpty(currStationId)){
            throw new BaseException("实体卡充值--油站不存在");
        }
        List<String> list = Arrays.stream(stationIds.split(",")).collect(Collectors.toList());
        if(!list.contains(currStationId)){
            throw new BaseException("实体卡充值--油站不属于充值油站");
        }
    }


    @PostMapping("/consumption")
    @ApiOperation(value = "实体卡消费",response = PhysicalCardSecretKeyDto.class)
    public AjaxResult consumption(@RequestBody PhysicalCardOrderDto physicalCardOrderDto){
        if(Objects.isNull(physicalCardOrderDto) || StringUtils.isEmpty(physicalCardOrderDto.getPhysicalCardNo())
                || StringUtils.isEmpty(physicalCardOrderDto.getMessage())){
            return AjaxResult.error("请求参数异常");
        }
        physicalCardOrderDto.setPhysicalCardNo(StringUtils.trim(physicalCardOrderDto.getPhysicalCardNo()));
        // 密文校验
        if(!checkMessage(physicalCardOrderDto.getMessage())){
            return AjaxResult.error("密文校验失败");
        }
        if(Objects.isNull(physicalCardOrderDto.getAmount())){
            return AjaxResult.error("请输入消费金额");
        }
        if(Objects.isNull(physicalCardOrderDto.getConsumptionStationId())){
            return AjaxResult.error("请输入油站");
        }
        if(com.alibaba.druid.util.StringUtils.isEmpty(physicalCardOrderDto.getOilGun())){
            return AjaxResult.error("请输入油枪号");
        }
        if(com.alibaba.druid.util.StringUtils.isEmpty(physicalCardOrderDto.getOilPersonnelId())){
            return AjaxResult.error("请输入加油员");
        }

        PayOrder payOrder = physicalCardOrderService.physicalCardConsumption(physicalCardOrderDto);
        log.info("poj机返回实体卡消费：[{}]",JSONObject.toJSONString(payOrder));
        PhysicalCardSecretKeyDto physicalCardSecretKeyDto = new PhysicalCardSecretKeyDto();
        BeanUtils.copyProperties(payOrder,physicalCardSecretKeyDto);
        physicalCardSecretKeyDto.setMobilePhone(payOrder.getCustomerPhone());
        physicalCardSecretKeyDto.setPhysicalCardNo(physicalCardOrderDto.getPhysicalCardNo());
        physicalCardSecretKeyDto.setSecretKeyA(SECRET_KEY_A);
        physicalCardSecretKeyDto.setPayTypeName("实体卡");

        return AjaxResult.success(physicalCardSecretKeyDto);
    }

    private boolean checkMessage(String message){
        String decrypt = "";
        try {
            decrypt = RSAUtils.decrypt(message, privateKey);
        } catch (Exception e){
            log.info("pos机密文校验失败：[{}]",e.getMessage());
            return false;
        }
        if(messageKey.equals(decrypt)){
            return true;
        }
        return false;
    }


    /**
     * 查询单个卡信息
     * */
    @GetMapping("/get")
    @ApiOperation(value = "查询单个卡信息",response = PhysicalCard.class)
    public AjaxResult getByNo(@RequestParam("physicalCardNo") String physicalCardNo){
        if(org.apache.commons.lang.StringUtils.isEmpty(physicalCardNo)){
            return AjaxResult.error("请求参数不存在");
        }
        physicalCardNo = StringUtils.trim(physicalCardNo);
        log.info("查询单个卡信息:[{}]",physicalCardNo);
        PhysicalCard physicalCard = physicalCardService.selectPhysicalCard(physicalCardNo);
        if(Objects.isNull(physicalCard)){
            return AjaxResult.error(400,"实体卡不存在");
        }
        return AjaxResult.success(physicalCard);
    }


//    /**
//     * 返回生产实体卡号
//     * */    /**
//     * 生成实体卡号
//     */
//    @GetMapping("/createNo")
//    @ApiOperation(value = "获取实体卡号",response = PhysicalCardSecretKeyDto.class)
//    public AjaxResult createNo(){
//        long physicalCardNo = SnowFlakeUtil.getDefaultSnowFlakeId();
//        PhysicalCardSecretKeyDto physicalCardSecretKeyDto = new PhysicalCardSecretKeyDto();
//        physicalCardSecretKeyDto.setPhysicalCardNo(String.valueOf(physicalCardNo));
//        physicalCardSecretKeyDto.setSecretKeyA(SECRET_KEY_A);
//        physicalCardSecretKeyDto.setSecretKeyB(SECRET_KEY_B);
//        return AjaxResult.success(physicalCardSecretKeyDto);
//    }

    /**
     * 新增实体卡  复制实体卡
     *
     * 双屏机、pos机开卡
     * */
    @PostMapping("/add")
    @ApiOperation(value = "新增实体卡、复制实体卡", response = PhysicalCardSecretKeyDto.class)
    public AjaxResult addPhysicalCard(@RequestBody PhysicalCard physicalCard){
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getPhysicalCardNo())){
            return AjaxResult.error("写卡卡号参数不能为空");
        }
        physicalCard.setPhysicalCardNo(StringUtils.trim(physicalCard.getPhysicalCardNo()));
        log.info("双屏机、pos机开卡 请求参数：[{}]",JSONObject.toJSONString(physicalCard));
        isCheck(physicalCard);
        if(Objects.nonNull(physicalCard.getPhysicalCardAmount())){
            long length = String.valueOf(physicalCard.getPhysicalCardAmount()).length();
            if(length >11){
                return AjaxResult.error("充值面额太大");
            }
        }
        if(Objects.isNull(physicalCard.getPhysicalCardAmount())){
            physicalCard.setPhysicalCardAmount(BigDecimal.ZERO);
        }

        physicalCard.setSecretKeyA(SECRET_KEY_A);
        physicalCard.setSecretKeyB(SECRET_KEY_B);
        physicalCardService.writePhysicalCard(physicalCard);
        PhysicalCardSecretKeyDto physicalCardSecretKeyDto = new PhysicalCardSecretKeyDto();
        physicalCardSecretKeyDto.setPhysicalCardNo(physicalCard.getPhysicalCardNo());
        physicalCardSecretKeyDto.setSecretKeyA(SECRET_KEY_A);
        physicalCardSecretKeyDto.setSecretKeyB(SECRET_KEY_B);
        return AjaxResult.success(physicalCardSecretKeyDto);
    }

    private void isCheck(PhysicalCard physicalCard){
        log.info("实体卡参数校验 isCheck：[{}]",JSONObject.toJSONString(physicalCard));
        if(Objects.isNull(physicalCard.getEnterpriseId())){
            throw new BaseException("请选择油企");
        }
        if(org.apache.commons.lang.StringUtils.isEmpty(physicalCard.getStationId())){
            throw new BaseException("请选择油站");
        }
        if(org.apache.commons.lang.StringUtils.isEmpty(physicalCard.getUserName())){
            throw new BaseException("请输入持卡人");
        }
        if(physicalCard.getUserName().length() > 20){
            throw new BaseException("输入持卡人姓名不要超过20个字符");
        }
        if(org.apache.commons.lang.StringUtils.isEmpty(physicalCard.getUserPhone())){
            throw new BaseException("请输入手机号");
        }
        //手机号校验
        if(!RegexUtils.isPhoneNum(physicalCard.getUserPhone())){
            throw new BaseException("请输入正确的手机号");
        }

    }

    @PostMapping("/withdraw")
    @ApiOperation("pos机、双屏机注销实体卡")
    public AjaxResult updatePhysicalCardStatus(@RequestParam("physicalCardNo") String physicalCardNo){
       if(StringUtils.isEmpty(physicalCardNo)){
           return AjaxResult.error("注销实体卡请求参数异常");
       }
       physicalCardNo = StringUtils.trim(physicalCardNo);
       log.info("pos机、双屏机注销实体卡请求参数：[{}]",physicalCardNo);
       PhysicalCard physicalCard = new PhysicalCard();
       physicalCard.setPhysicalCardNo(physicalCardNo);
       physicalCard.setCardStatus("2");
       int num = physicalCardService.updatePhysicalCardStatus(physicalCard);
       if(num <= 0){
           return AjaxResult.error("注销实体卡请求参数异常");
       }
        return AjaxResult.success("实体卡注销成功");
    }

    @GetMapping("/stations")
    public AjaxResult getStations(@RequestParam("stationId") Long stationId){
        if(Objects.isNull(stationId)){
            return AjaxResult.error("请求参数异常");
        }
        log.info("getStations 请求参数：[{}]",stationId);
        List<Map<String, Object>> stationList = physicalCardService.getStationList(stationId);
        log.info("getStations 响应结果：[{}]",stationList);
        return AjaxResult.success(stationList);
    }

    /** 修改实体卡状态注销状态*/
    @PostMapping("/update/status")
    @ApiOperation("实体卡注销状态")
    public AjaxResult updatePhysicalCardStatus(@RequestBody PhysicalCard physicalCard){
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getPhysicalCardNo())){
            return AjaxResult.error("请求参数异常");
        }
        physicalCard.setPhysicalCardNo(StringUtils.trim(physicalCard.getPhysicalCardNo()));
        log.info("实体卡注销状态:[{}]",JSONObject.toJSONString(physicalCard));
        int num = physicalCardService.updatePhysicalCardStatus(physicalCard);
        if(num <= 0){
            return AjaxResult.error("实体卡注销失败");
        }

        return AjaxResult.success("实体卡注销成功");
    }

    /** 修改实体卡信息*/
    @PostMapping("/update/values")
    @ApiOperation("实体卡注销状态")
    public AjaxResult updatePhysicalCard(@RequestBody PhysicalCard physicalCard){
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getPhysicalCardNo())){
            return AjaxResult.error("请求参数异常");
        }
        physicalCard.setPhysicalCardNo(StringUtils.trim(physicalCard.getPhysicalCardNo()));
        log.info("实体卡信息:[{}]",JSONObject.toJSONString(physicalCard));
        int num = physicalCardService.updatePhysicalCardStatus(physicalCard);
        if(num <= 0){
            return AjaxResult.error("实体卡修改失败");
        }

        return AjaxResult.success("实体卡修改成功");
    }

}
